

//interrupt code to read RIGHT linear encoder
void doEncoder0A(){

  // look for a low-to-high on channel A
  if (digitalRead(encoder0PinA) == HIGH) { 
    // check channel B for encoder direction
    if (digitalRead(encoder0PinB) == LOW) {  
      encoder0Pos++;                         // CW
      encoder0Pos = min(encoder0Pos, 127);
    } 
    else {
      encoder0Pos--;                         // CCW
      encoder0Pos = max(encoder0Pos, 0);
    }
  }
  else   // must be a high-to-low edge on channel A                                       
  { 
    // check channel B for encoder direction
    if (digitalRead(encoder0PinB) == HIGH) {   
      encoder0Pos++;          // CW
      encoder0Pos = min(encoder0Pos, 127);     
    } 
    else {
      encoder0Pos--;          // CCW
      encoder0Pos = max(encoder0Pos, 0); 
    }
  }
}

void doEncoder0B(){

  // look for a low-to-high on channel B
  if (digitalRead(encoder0PinB) == HIGH) {   
    // check channel A for encoder direction
    if (digitalRead(encoder0PinA) == HIGH) {  
      encoder0Pos++;         // CW
      encoder0Pos = min(encoder0Pos, 127);  
    } 
    else {
      encoder0Pos--;         // CCW
      encoder0Pos = max(encoder0Pos, 0);
    }
  }
  // Look for a high-to-low on channel B
  else { 
    // check channel B for encoder direction  
    if (digitalRead(encoder0PinA) == LOW) {   
      encoder0Pos++;          // CW
      encoder0Pos = min(encoder0Pos, 127);  
    } 
    else {
      encoder0Pos--;          // CCW
      encoder0Pos = max(encoder0Pos, 0);
    }
  }
}


//interrupt code to read LEFT linear encoder

void doEncoder1A(){

  // look for a low-to-high on channel A
  if (digitalRead(encoder1PinA) == HIGH) { 
    // check channel B for encoder direction
    if (digitalRead(encoder1PinB) == LOW) {  
      encoder1Pos++;                         // CW
      encoder1Pos = min(encoder1Pos, 127);
    } 
    else {
      encoder1Pos--;                         // CCW
      encoder1Pos = max(encoder1Pos, 0);
    }
  }
  else   // must be a high-to-low edge on channel A                                       
  { 
    // check channel B for encoder direction 
    if (digitalRead(encoder1PinB) == HIGH) {   
      encoder1Pos++;          // CW
      encoder1Pos = min(encoder1Pos, 127);     
    } 
    else {
      encoder1Pos--;          // CCW
      encoder1Pos = max(encoder1Pos, 0); 
    }
  }
}

void doEncoder1B(){

  // look for a low-to-high on channel B
  if (digitalRead(encoder1PinB) == HIGH) {   
    // check channel A for encoder direction
    if (digitalRead(encoder1PinA) == HIGH) {  
      encoder1Pos++;         // CW
      encoder1Pos = min(encoder1Pos, 127);  
    } 
    else {
      encoder1Pos--;         // CCW
      encoder1Pos = max(encoder1Pos, 0);
    }
  }
  // Look for a high-to-low on channel B
  else { 
    // check channel B for encoder direction
    if (digitalRead(encoder1PinA) == LOW) {   
      encoder1Pos++;          // CW
      encoder1Pos = min(encoder1Pos, 127);  
    } 
    else {
      encoder1Pos--;          // CCW
      encoder1Pos = max(encoder1Pos, 0);
    }
  }
}

boolean pulse_flag = true;



//Timer2 overflow interrupt vector handler
ISR(TIMER2_OVF_vect) {
  //*************blink BPM LED***************
  cli();
  int led_out = PULSE_TABLE[phase>>8];   //blinkie LED on board that follows wavetable frequency
  if (inhibit_LED == false)     //no blinkies while reading BPM use a timer in the loop to pulse the LED instead
    analogWrite (wave_led_pin, led_out);

  //************receive midi clock*******************
  if(Serial3.available() > 0) {       //take care of all the time-sensitive midi clock input
    data = Serial3.read();
    if(data == midi_start ) {
      play_flag = 1;
      phase = 0;
    }
    else if((data == midi_clock) && (play_flag == 1)) {
      midi_ticks = midi_ticks++;  //increment the two output channels
      count_sync = count_sync++;   //this count_sync allows value changes at the quarter note
      if (count_sync == 24 )
        count_sync = 0;
      if (midi_ticks == Subdivision) {    //reached the # of ticks **** put in Subdivision variable here?
        midi_tap = true;
        midi_beat_time = millis();
        midi_ticks = 0;
        if (count_sync == 0) //only if we are synched to the beat then accept new value 
          subdivide = true;
      }
    }
  }
  //************send midi clock*****************
  if (play_flag != 1) {   //if receiving midi clock, don't send clock

//    subdivide = true;  //check subdivision selection

    if (start_flag == true) {     //send out the midi start and synch the LFO in a nice orderly manner
      phase = 0;      //reset waveform on midi start
      Serial3.print(midi_start, BYTE);
      start_flag = false;
    }
    
    phase_tab = phase*(Subdivision_out);                      //advance the table reading by switch setting  
    int midi_tick_out = MIDI_TICK_TABLE[phase_tab>>8];
    
    if (midi_tick_out == 0xff && pulse_flag == false && midi_clock_flag == true) {   //flag needed so we don't get multiple midi writes
      pulse_flag = true;
      count_out_sync = count_out_sync++;
      Serial3.print(midi_clock, BYTE);         //send ticks 
      if (count_out_sync == 24 ) {                  //synch beat subdivisons on midi quarter note doesn't work in all instances
       count_out_sync = 0;                          //may need more than just synching on beat & include subdivison too
       subdivide = true;
      }
    }
    else if (midi_tick_out == 0x00 && pulse_flag == true && midi_clock_flag == true)   //reset the flag
      pulse_flag = false;
 
  }

  //************output waveforms*********************
  for(int i=0; i < 4; i++) {                   //output the four channels of waveforms
    if (wave_channel[i] != 0) {
      resistance = *(waveArr[i] + (phase>>8));  // pull out the waveshape by channel
      write_pot_a(i,resistance);
    }    
  }
  phase += phaseDelta;
  sei();


  //*************run other non-waveform functions per channel***************
  functArr[I](I);       // run one state machine once per interrupt
  I = I++;
  if (I > 3) {
    I = 0;
  }
  //Capture the current timer value. This is how much error we have
  //due to interrupt latency and the work in this function
  // put this at the end of a time sensitive function and it will correct the timer interrupt fire
  latency=TCNT2;

  //Reload the timer and correct for latency.  //Reload the timer and correct for latency.  //Reload the timer and correct for latency.
  TCNT2=latency+timerLoadValue; 
}







